﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace OpiConsole
{
    public abstract class Command
    {
        protected static OpiConsole.Console console;
        protected static Game m_pGame;
        protected static Object m_pGameManager;

        public String Name
        {
            get { return m_sCommandName; }
        }
        private String m_sCommandName;

        public String Usage
        {
            get { return m_sCommandUsage; }
        }
        private String m_sCommandUsage;

        public UsageLevel UsageLevel
        {
            get { return m_eUsageLevel; }
        }
        private UsageLevel m_eUsageLevel;

        protected Command(Game game, Console con, Object gameManager)
        {
            m_pGame = game;
            console = con;
            m_pGameManager = gameManager;
        }

        protected Command(String cmdName, String usage, UsageLevel usageLevel)
        {
            m_sCommandName = cmdName;
            m_sCommandUsage = usage;
            m_eUsageLevel = usageLevel;
        }

        public abstract bool Invoke(List<string> args);

    }

    #region Default_Commands
    public class Command_Init : Command
    {
        public Command_Init(Game game, OpiConsole.Console console, Object gameManager)
            : base(game, console, gameManager)
        {
        }

        public override bool Invoke(List<string> args)
        {
            return true;
        }
    }

    public class Command_CLS : Command
    {
        public Command_CLS()
            : base("cls", "Clears the screen", UsageLevel.NORMAL)
        {
        }

        public override bool Invoke(List<string> args)
        {
            console.Clear();
            return true;
        }
    }

    public class Command_Quit : Command
    {
        public Command_Quit()
            : base("quit", "Exits the game", UsageLevel.NORMAL)
        {
        }

        public override bool Invoke(List<string> args)
        {
            m_pGame.Exit();
            return true;
        }
    }

    public class Command_CVar : Command
    {
        public Command_CVar()
            : base("cvar", "Allows you to view and modify CVars", UsageLevel.NORMAL)
        {
        }

        public override bool Invoke(List<string> args)
        {
            if (args.Count < 1)
                return false;

            String cvarName = args[0];
            List<String> tmpArgs = new List<String>(args);
            tmpArgs.RemoveAt(0);

            if (console.HasCVar(cvarName))
            {
                console.setCVar(cvarName, tmpArgs);
            }
            else
                return false;

            return true;
        }
    }

    public class Command_Help : Command
    {
        public Command_Help()
            : base("help", "Displays help about commands", UsageLevel.NORMAL)
        {
        }

        public override bool Invoke(List<string> args)
        {
            if (args.Count <= 0)
                return false;

            console.Print(console.GetCommand(args[0]).Usage, ConsoleLevel.NORM);
            return true;
        }
    }

    public class Command_ListCommands : Command
    {
        public Command_ListCommands()
            : base("listCommands", "Lists all available commands", UsageLevel.DEV)
        {
        }

        public override bool Invoke(List<string> args)
        {
            List<string> cmds = console.GetCommands();
            string output = "Available Commands: ";
            foreach (string s in cmds)
            {
                if (console.GetCommand(s).UsageLevel < console.UserLevel)
                    continue;
                
                output += s + ", ";
            }
            output = output.Remove(output.Length - 2, 2);
            console.Print(output);
            return true;
        }
    }

    public class Command_SaveConfig : Command
    {
        public Command_SaveConfig()
            : base("saveConfig", "Saves the current CVar values to the config file.", UsageLevel.DEV)
        {
        }

        public override bool Invoke(List<string> args)
        {
            console.SaveConfig();
            return true;
        }
    }

    public class Command_LoadConfig : Command
    {
        public Command_LoadConfig()
            : base("loadConfig", "Loads the CVar values in the config file to the current CVars.", UsageLevel.DEV)
        {
        }

        public override bool Invoke(List<string> args)
        {
            console.LoadConfig();
            return true;
        }
    }
    #endregion
}
